/*********************************************************
 * File:TreeView.java
 * 
 * Version 2.0
 * 
 * Date     2005-4-28
 * Author   HanZhanYuan
 * 
 * Copyright (C) 2005 VandaGroup.
 * all rights reserved.
 * 
 ********************************************************/

package com.vandagroup.portal.menu.treeview;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.HashSet;

import javax.servlet.jsp.JspWriter;

import com.vandagroup.common.po.PortalPO;
import com.vandagroup.common.resources.SysPara;

/**
 * @author HanZhanYuan 說明：
 */
public class TreeView {

	private String contexPath = "..";

	/**
	 * @return Returns the contexPath.
	 */
	public String getContexPath() {
		return contexPath;
	}

	/**
	 * @param contexPath
	 *            The contexPath to set.
	 */
	public void setContexPath(String contexPath) {

		this.contexPath = contexPath;
	}

	/**
	 * 樹狀菜單類型：帶radio的樹狀菜單
	 */
	public static int RADIO = 1;

	/**
	 * 樹狀菜單類型：帶checkbox的樹狀菜單
	 */
	public static int CHECKBOX = 2;

	/**
	 * Create Date : 2004-1-17
	 */
	public TreeView() {
		super();
	}

	/**
	 * 構造函數：生成基本型樹狀功能表，強制在頁面javascript中實現“clickFolder()、clickLeaf()”方法 <br>
	 * 方法接收的參數為兩個，即 <br>
	 * arguments[ 0 ]=colValue <br>
	 * arguments[ 1 ]=colText <br>
	 * <br>
	 * 
	 * @param title
	 *            樹狀菜單標題 <br>
	 * @param tableName
	 *            表名 <br>
	 * @param colName
	 *            主欄位名稱 <br>
	 * @param textColName
	 *            主欄位顯示文字欄位 <br>
	 * @param parentColName
	 *            父欄位名稱 <br>
	 * @param parentColValue
	 *            父欄位初始值 <br>
	 *            Create Date : 2004-1-17 <br>
	 */
	public TreeView(String title, String tableName, String colName,
			String textColName, String parentColName, String parentColValue)
			throws Exception {

		setTitle(title);
		setTableName(tableName);
		setColName(colName);
		setTextColName(textColName);
		setParentColName(parentColName);
		setParentColValue(parentColValue);
	}

	/**
	 * 構造函數：生成基本型樹狀功能表，強制在頁面javascript中實現“clickFolder()、clickLeaf()”方法 <br>
	 * 方法接收的參數為三個，即 <br>
	 * arguments[ 0 ]=colValue <br>
	 * arguments[ 1 ]=colText <br>
	 * arguments[ 2 ]=paraValue(參數欄位的值) <br>
	 * <br>
	 * 
	 * @param title
	 *            樹狀菜單標題 <br>
	 * @param tableName
	 *            表名 <br>
	 * @param colName
	 *            主欄位名稱 <br>
	 * @param textColName
	 *            主欄位顯示文字欄位 <br>
	 * @param parentColName
	 *            父欄位名稱 <br>
	 * @param parentColValue
	 *            父欄位初始值 <br>
	 * @param paraColName
	 *            參數欄位名稱 <br>
	 *            Create Date : 2004-1-17 <br>
	 */
	public TreeView(String title, String tableName, String colName,
			String textColName, String parentColName, String parentColValue,
			String paraColName) throws Exception {

		setTitle(title);
		setTableName(tableName);
		setColName(colName);
		setTextColName(textColName);
		setParentColName(parentColName);
		setParentColValue(parentColValue);
		setParaColName(paraColName);
	}

	/**
	 * 帶“checkbox”或“radio”的樹狀菜單被選中的值的集合
	 */
	private String[] checkValue = null;

	/**
	 * 顯示到頁面上的html代碼
	 */
	private StringBuffer html = null;

	/**
	 * 表名
	 */
	private String tableName = null;

	/**
	 * 主欄位名稱
	 */
	private String colName = null;

	/**
	 * 主欄位顯示文字欄位
	 */
	private String textColName = null;

	/**
	 * 父欄位名稱
	 */
	private String parentColName = null;

	/**
	 * 父欄位初始值
	 */
	private String parentColValue = null;

	/**
	 * 菜單項被點擊獲得的參數欄位名稱
	 */
	private String paraColName = null;

	/**
	 * “是否葉節點”標識欄位
	 */
	private String isLeafColName = null;

	/**
	 * “是葉節點”對應的標識值
	 */
	private String isLeaf = null;

	/**
	 * “不是葉節點”對應的標識值
	 */
	private String isNotLeaf = null;

	/**
	 * 顯示在功能表最頂層的標題
	 */
	private String title = null;

	private String imgTreeHead = null;

	private String imgPlus = null;

	private String imgMinus = null;

	private String imgFolder = null;

	private String imgNode = null;

	private String imgTrans = null;

	private String whereClause = null;

	/**
	 * @return String
	 */
	public String getColName() {
		return colName;
	}

	/**
	 * @return String
	 */
	public String getIsLeaf() {
		return isLeaf;
	}

	/**
	 * @return String
	 */
	public String getIsLeafColName() {
		return isLeafColName;
	}

	/**
	 * @return String
	 */
	public String getIsNotLeaf() {
		return isNotLeaf;
	}

	/**
	 * @return String
	 */
	public String getParaColName() {
		return paraColName;
	}

	/**
	 * @return String
	 */
	public String getParentColName() {
		return parentColName;
	}

	/**
	 * @return String
	 */
	public String getParentColValue() {
		return parentColValue;
	}

	/**
	 * @return String
	 */
	public String getTableName() {
		return tableName;
	}

	/**
	 * Sets the colName.
	 * 
	 * @param colName
	 *            The colName to set
	 */
	public void setColName(String colName) {
		this.colName = colName;
	}

	/**
	 * Sets the isLeaf.
	 * 
	 * @param isLeaf
	 *            The isLeaf to set
	 */
	public void setIsLeaf(String isLeaf) {
		this.isLeaf = isLeaf;
	}

	/**
	 * Sets the isLeafColName.
	 * 
	 * @param isLeafColName
	 *            The isLeafColName to set
	 */
	public void setIsLeafColName(String isLeafColName) {
		this.isLeafColName = isLeafColName;
	}

	/**
	 * Sets the isNotLeaf.
	 * 
	 * @param isNotLeaf
	 *            The isNotLeaf to set
	 */
	public void setIsNotLeaf(String isNotLeaf) {
		this.isNotLeaf = isNotLeaf;
	}

	/**
	 * Sets the paraColName.
	 * 
	 * @param paraColName
	 *            The paraColName to set
	 */
	public void setParaColName(String paraColName) {
		this.paraColName = paraColName;
	}

	/**
	 * Sets the parentColName.
	 * 
	 * @param parentColName
	 *            The parentColName to set
	 */
	public void setParentColName(String parentColName) {
		this.parentColName = parentColName;
	}

	/**
	 * Sets the parentColValue.
	 * 
	 * @param parentColValue
	 *            The parentColValue to set
	 */
	public void setParentColValue(String parentColValue) {
		this.parentColValue = parentColValue;
	}

	/**
	 * Sets the tableName.
	 * 
	 * @param tableName
	 *            The tableName to set
	 */
	public void setTableName(String tableName) {
		this.tableName = tableName;
	}

	/**
	 * @return String
	 */
	public String getTextColName() {
		return textColName;
	}

	/**
	 * Sets the textColName.
	 * 
	 * @param textColName
	 *            The textColName to set
	 */
	public void setTextColName(String textColName) {
		this.textColName = textColName;
	}

	/**
	 * @return String
	 */
	public String getTitle() {
		return title;
	}

	/**
	 * Sets the title.
	 * 
	 * @param title
	 *            The title to set
	 */
	public void setTitle(String title) {
		this.title = title;
	}

	/**
	 * @return String
	 */
	public String getImgFolder() {
		return imgFolder;
	}

	/**
	 * @return String
	 */
	public String getImgMinus() {
		return imgMinus;
	}

	/**
	 * @return String
	 */
	public String getImgNode() {
		return imgNode;
	}

	/**
	 * @return String
	 */
	public String getImgPlus() {
		return imgPlus;
	}

	/**
	 * @return String
	 */
	public String getImgTrans() {
		return imgTrans;
	}

	/**
	 * @return String
	 */
	public String getImgTreeHead() {
		return imgTreeHead;
	}

	/**
	 * Sets the imgFolder.
	 * 
	 * @param imgFolder
	 *            The imgFolder to set
	 */
	public void setImgFolder(String imgFolder) {
		this.imgFolder = imgFolder;
	}

	/**
	 * Sets the imgMinus.
	 * 
	 * @param imgMinus
	 *            The imgMinus to set
	 */
	public void setImgMinus(String imgMinus) {
		this.imgMinus = imgMinus;
	}

	/**
	 * Sets the imgNode.
	 * 
	 * @param imgNode
	 *            The imgNode to set
	 */
	public void setImgNode(String imgNode) {
		this.imgNode = imgNode;
	}

	/**
	 * Sets the imgPlus.
	 * 
	 * @param imgPlus
	 *            The imgPlus to set
	 */
	public void setImgPlus(String imgPlus) {
		this.imgPlus = imgPlus;
	}

	/**
	 * Sets the imgTrans.
	 * 
	 * @param imgTrans
	 *            The imgTrans to set
	 */
	public void setImgTrans(String imgTrans) {
		this.imgTrans = imgTrans;
	}

	/**
	 * Sets the imgTreeHead.
	 * 
	 * @param imgTreeHead
	 *            The imgTreeHead to set
	 */
	public void setImgTreeHead(String imgTreeHead) {
		this.imgTreeHead = imgTreeHead;
	}

	/**
	 * @return String
	 */
	public String getWhereClause() {
		return whereClause;
	}

	/**
	 * Sets the whereClause.
	 * 
	 * @param whereClause
	 *            The whereClause to set
	 */
	public void setWhereClause(String whereClause) {
		this.whereClause = whereClause;
	}

	/**
	 * Sets the whereClause.
	 * 
	 * @param whereClause
	 *            The whereClause to set
	 */
	public void setWhereClause(String whereClause, String loginType)
			throws Exception {
		// System.out.println("the loginType is :" + loginType);
		if (loginType.equals(SysPara.INPUT_TYPE)) {// 錄入員，無授權功能
			this.whereClause = whereClause + " AND FUNCID <> '"
					+ SysPara.TranAuthID + "'";
		} else {
			this.whereClause = whereClause;
		}
	}

	/**
	 * 生成javascript中生成樹狀功能表使用的陣列
	 * 
	 * @throws Exception
	 *             Create Date : 2004-1-17
	 */
	private HashSet IDSet = new HashSet();

	public void genSubject(TreeConnection treeConn, String fid)
			throws Exception {

		if (!IDSet.contains(fid)) {
			Statement stmt = treeConn.getConn().createStatement();
			String sql = "select "
					+ this.parentColName
					+ ", "
					+ this.colName
					+ ", "
					+ this.textColName
					+ (this.paraColName == null ? "'t' T" : ", "
							+ this.paraColName) + " from " + tableName
					+ " where " + this.colName + "='" + fid + "'";
			ResultSet rs = stmt.executeQuery(sql);
			if (rs.next()) {

				IDSet.add(convert(rs.getString(2)));
				genSubject(treeConn, convert(rs.getString(1)));
				html.append("_arrTreeView[ _arrTreeView.length ] = new Array(");
				html.append("\"" + convert(rs.getString(1)) + "\",");
				html.append("\"" + convert(rs.getString(2)) + "\",");
				html.append("\"" + convert(rs.getString(3)) + "\",");
				if (convert(rs.getString(4)) != null)
					html.append(this.paraColName == null ? "\"\"" : "\""
							+ this.contexPath + convert(rs.getString(4)).trim()
							+ "&_funcID=" + convert(rs.getString(2)) + "\"");
				else
					html.append("\"\"");
				html.append(");\n");
			}
		}
	}

	private HashMap indexHM = new HashMap();

	private void createIndex(TreeConnection treeConn) throws Exception {
		Statement stmt = null;
		ResultSet rs = null;

		String sql = "select "
				+ this.colName
				+ ", "
				+ this.parentColName
				+ " from "
				+ tableName
				+ (this.whereClause == null ? "" : (" where " + this.colName
						+ " IN (" + this.whereClause + ") "));
		stmt = treeConn.getConn().createStatement();
		rs = stmt.executeQuery(sql);
		while (rs.next()) {
			indexHM.put(convert(rs.getString(1)), convert(rs.getString(2)));
		}
	}

	private boolean isSubNode(String id, String subID) {
		if (id.equals("$$$$$$$$"))
			return true;
		if (id.equals(subID))
			return false;
		boolean isTrue = false;
		String tid = subID;
		while (indexHM.get(tid) != null) {
			tid = (String) indexHM.get(tid);
			if (id.equals(tid))
				return true;
		}
		return isTrue;
	}

	public void create() throws Exception {

		if (this.tableName == null)
			throw new Exception("表名不能為空！");
		if (this.colName == null)
			throw new Exception("主欄位名稱不能為空！");
		if (this.textColName == null)
			throw new Exception("主欄位顯示文字欄位不能為空！");
		if (this.parentColName == null)
			throw new Exception("父欄位名稱不能為空！");
		if (this.parentColValue == null)
			throw new Exception("父欄位初始值不能為空！");

		Statement stmt = null;
		ResultSet rs = null;
		IDSet.add(this.parentColValue);
		TreeConnection treeConn = new TreeConnection();
		try {
			StringBuffer sql = new StringBuffer();

			sql
					.append("select "
							+ this.parentColName
							+ ", "
							+ this.colName
							+ ", "
							+ this.textColName
							+ (this.paraColName == null ? ", 't' T " : ", "
									+ this.paraColName)
							+ " from "
							+ tableName
							+ (this.whereClause == null ? ""
									: (" where " + this.colName + " IN ("
											+ this.whereClause + ") "))
							+ " ORDER BY " + this.colName);

			treeConn.begin();

			if (!this.parentColValue.equals("$$$$$$$$")) {
				this.createIndex(treeConn);
			}
			stmt = treeConn.getConn().createStatement();
			rs = stmt.executeQuery(sql.toString());

			html = new StringBuffer();
			html.append("<script language='javascript'>\n");
			html.append("<!--\n");
			html.append("var _arrTreeView = new Array();\n");
			while (rs.next()) {
				if (!isSubNode(this.parentColValue, convert(rs.getString(2)))) {
					continue;
				}
				if (IDSet.contains(convert(rs.getString(2))))
					continue;
				IDSet.add(convert(rs.getString(2)));
				if (!convert(rs.getString(1)).equals(this.parentColValue)) {
					genSubject(treeConn, convert(rs.getString(1)));
				}
				html.append("_arrTreeView[ _arrTreeView.length ] = new Array(");
				html.append("\"" + convert(rs.getString(1)) + "\",");
				html.append("\"" + convert(rs.getString(2)) + "\",");
				html.append("\"" + convert(rs.getString(3)) + "\",");
				if (convert(rs.getString(4)) != null)
					html.append(this.paraColName == null ? "\"\"" : "\""
							+ this.contexPath + convert(rs.getString(4)).trim()
							+ "&_funcID=" + convert(rs.getString(2)) + "\"");
				else
					html.append("\"\"");
				html.append(");\n");
			}
			// System.out.println(sql.toString());
			html.append(this.imgTreeHead == null ? "" : "_imgTreeHead = \""
					+ this.imgTreeHead + "\"\n");
			html.append(this.imgPlus == null ? "" : "_imgPlus = \""
					+ this.imgPlus + "\"\n");
			html.append(this.imgMinus == null ? "" : "_imgMinus = \""
					+ this.imgMinus + "\"\n");
			html.append(this.imgFolder == null ? "" : "_imgFolder = \""
					+ this.imgFolder + "\"\n");
			html.append(this.imgNode == null ? "" : "_imgNode = \""
					+ this.imgNode + "\"\n");
			html.append(this.imgTrans == null ? "" : "_imgTrans = \""
					+ this.imgTrans + "\"\n");
			html.append("var treeView = new TreeView(\"" + this.parentColValue
					+ "\", \"" + this.title + "\");\n");

			html.append("-->\n");
			html.append("</script>");
		} catch (SQLException se) {
			se.printStackTrace();
			throw se;
		} catch (Exception e) {
			e.printStackTrace();
			throw e;
		} finally {
			try {
				if (rs != null) {
					rs.close();
				}
			} catch (Throwable e) {
				System.out.println("TreeView rs close error");
				e.printStackTrace();
			}

			try {
				if (stmt != null) {
					stmt.close();
				}
			} catch (Throwable e) {
				System.out.println("TreeView stmt close error");
				e.printStackTrace();
			}

			try {
				treeConn.free();
			} catch (Throwable e) {
				System.out.println("TreeView conn close error");
				e.printStackTrace();
			}
		}
	}

	private PortalPO convertPo = new PortalPO();

	private String convert(String inputStr) {
		if (inputStr == null) {
			return (null);
		}
		return (convertPo.convert(inputStr));
	}

	/**
	 * 顯示功能表
	 * 
	 * @param out
	 *            Create Date : 2004-1-17
	 */
	public void display(JspWriter out) throws Exception {
		out.println(html.toString());
	}

}
